package ch.fhnw.kosmonauten.server.net;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.sql.SQLException;

import ch.fhnw.kosmonauten.model.Category;
import ch.fhnw.kosmonauten.model.Dossier;
import ch.fhnw.kosmonauten.model.User;
import ch.fhnw.kosmonauten.net.LoginRequest;
import ch.fhnw.kosmonauten.net.Message;
import ch.fhnw.kosmonauten.net.Request;
import ch.fhnw.kosmonauten.net.Response;
import ch.fhnw.kosmonauten.net.TextMessage;
import ch.fhnw.kosmonauten.server.dal.CategoryAccessLayer;
import ch.fhnw.kosmonauten.server.dal.HexagramAccessLayer;
import ch.fhnw.kosmonauten.server.dal.DossierAccessLayer;
import ch.fhnw.kosmonauten.server.dal.UserAccessLayer;
import ch.fhnw.kosmonauten.server.net.dto.Transformation;

/**
 * Diese Klasse ermoeglicht die Kommunikation zwischen Server und Klient.
 * 
 * @author Fabian Siegrist
 * @author Oliver Freiermuth
 * @author Mikhail Onoufrienko
 * @author Risto Milani
 * @version $Revision: 210 $
 *          File name: $HeadURL: http://iching-kosmonauten.googlecode.com/svn/I-Ching/src/ch/fhnw/kosmonauten/server/net/ClientWorker.java $
 *          Last modified:$Date: 2013-05-27 17:56:04 +0000 (Mon, 27 May 2013) $
 *          Last modified by: $Author: molotok.mihon@gmail.com $
 */

// class definition
public class ClientWorker implements Runnable {

	// attributes
	private final MultiThreadedServer parent;
	private final Socket client;
	ObjectOutputStream serverOut;
	ObjectInputStream serverIn;
	private Transformation trans;
	private CategoryAccessLayer cal;
	private Dossier dossier;
	private User user;
	private Category cat;

	// constructor
	// private CategoryAccessLayer cal;
	/**
	 * @param parent
	 * @param client
	 * @param serverOut
	 * @throws IOException
	 */
	public ClientWorker(MultiThreadedServer parent, Socket client,
			ObjectOutputStream serverOut) throws IOException {
		this.parent = parent;
		this.client = client;
		this.serverOut = serverOut;
		this.serverIn = new ObjectInputStream(this.client.getInputStream());
		parent.log("ClientWorker created");
	}

	// methods
	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Runnable#run()
	 */
	@Override
	public void run() {
		parent.log("Client connected.");
		parent.log("ClientConnnection: "
				+ client.getInetAddress().getHostAddress() + ":"
				+ client.getPort());
		try {
			Message msg = null;
			while ((msg = (Message) serverIn.readObject()) != null) {
				if (msg instanceof TextMessage) {
					parent.log("Client did send Message:"
							+ msg.getContent().toString());
					serverOut.writeObject(new TextMessage(
							"Hey thanks, welcome to Server!"));
				} else if (msg instanceof Request) {
					if (msg.getType().equals(LoginRequest.type)) {
						LoginRequest lg = (LoginRequest) msg.getContent();
						parent.log("Client try to login:"
								+ lg.getUsername().toString());
						if (lg.getUsername().length() > 0 && lg.getPassword().length() > 0) {
							trans = new Transformation();
							User user = trans.getUser(lg.getUsername(),
									lg.getPassword());
							if (user == null) {
								serverOut.writeObject(new Response(new String(
										"Database Error."), "Error"));
							} else {
								serverOut.writeObject(new Response(user, "User"));
							}
						} else
							serverOut.writeObject(new Response(new String(
									"Wrong password or username."), "Object"));
					} 
					else if (msg.getType().equals("getCategories")) {
						parent.log("Client try get categories");
						serverOut.writeObject(new Response(new CategoryAccessLayer().getCategories(),"getCategories"));
					} 
					else if (msg.getType().equals("getHexagramTextSitAndPer")) 
					{
						this.dossier = (Dossier)msg.getContent();
						parent.log("Client try to get hexgramtext, UserID: " + Integer.toString(dossier.getUserID()));
						if (dossier.getBinarycode().length() == 6 && dossier.getBinarycodePerspective().length() == 6) {
							serverOut.writeObject(new Response(new HexagramAccessLayer().getHexagram(dossier),"getHexagramTextSitAndPer"));
						} else
							serverOut.writeObject(new Response(new String("Wrong binary code."), "Object"));
					} 
					else if (msg.getType().equals("saveDossier")) 
					{
						this.dossier = (Dossier)msg.getContent();
						parent.log("Client try to create dossier, UserID: " + Integer.toString(dossier.getUserID()));
						serverOut.writeObject(new Response(new DossierAccessLayer().createDossier(dossier),"saveDossier"));
					} 
					else if (msg.getType().equals("saveAsDossier")) 
					{
						this.dossier = (Dossier)msg.getContent();
						parent.log("Client try to save dossier, UserID: " + Integer.toString(dossier.getUserID()));
						serverOut.writeObject(new Response(new DossierAccessLayer().saveDossier(dossier),"saveAsDossier"));
					}
					else if (msg.getType().equals("saveUserProfile")) 
					{
						this.user = (User)msg.getContent();
						parent.log("Client try to save user profile, UserID: " + Integer.toString(user.getId()));
						serverOut.writeObject(new Response(new UserAccessLayer().saveUser(user),"saveUserProfile"));	
					}
					else if (msg.getType().equals("updateCategoryName")) 
					{
						this.cat = (Category)msg.getContent();
						parent.log("Client try to update Category name, CategoryID: " + cat.getCategoryID());
						serverOut.writeObject(new Response(new CategoryAccessLayer().changeCategory(cat),"updateCategory"));
					}
					else if (msg.getType().equals("createCategory")) 
					{
						this.cat = (Category)msg.getContent();
						parent.log("Client try to create a Category");
						serverOut.writeObject(new Response(new CategoryAccessLayer().setCategory(cat),"createCategory"));
					}
					else if (msg.getType().equals("getUsers")) {
						parent.log("Client try get users");
						serverOut.writeObject(new Response(new UserAccessLayer().getUsers(),"getUsers"));
					}
					else if (msg.getType().equals("adminSaveUserProfile")) 
					{
						this.user = (User)msg.getContent();
						parent.log("Client Admin try to save user profile, UserID: " + Integer.toString(user.getId()));
						serverOut.writeObject(new Response(new UserAccessLayer().adminSaveUser(user),"saveUserProfile"));	
					}
					else if (msg.getType().equals("createUserProfile")) 
					{
						this.user = (User)msg.getContent();
						parent.log("Client Admin try to create user profile, Username: " + user.getUsername());
						serverOut.writeObject(new Response(new UserAccessLayer().createUser(user),"createUserProfile"));	
					}
					else if (msg.getType().equals("getDossierList")) 
					{
						this.user = (User)msg.getContent();
						parent.log("Client try to load dossiers, UserID: " + Integer.toString(user.getId()));
						serverOut.writeObject(new Response(new DossierAccessLayer().getDossierLoad(user),"getDossierList"));	
					}
					else
						serverOut.writeObject(new Response(new String("Wrong server command."), "Object"));

				}
				// break;
			}
			serverIn.close();
			client.close();
			parent.i--;
			parent.log("client.close()");
		} catch (EOFException e) {
			// its okey client did close connection without say bye... naughty
			// client!
			e.printStackTrace();
		} catch (IOException e) {
			try {
				throw new IOException(e);
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		} catch (ClassNotFoundException e) {
			throw new RuntimeException(e);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				serverIn.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				client.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			parent.i--;
		}
	}
}